package org.xxpay.pay.channel.zypay;

import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayNotify;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author: pangxiaoyu
 * @date: 2019年8月12日10:34:08
 */
@Service
public class ZypayPayNotifyService extends BasePayNotify {

    private static final MyLog _log = MyLog.getLog(ZypayPayNotifyService.class);
    private static final String logPrefix = "【处理"+ ZypayConfig.CHANNEL_NAME+"支付回调】";

    @Override
    public String getChannelName() {
        return ZypayConfig.CHANNEL_NAME;
    }

    @Override
    public JSONObject doNotify(Object notifyData) {
        _log.info("====== 开始处理ZY支付回调通知 ======");
        HttpServletRequest request = (HttpServletRequest) notifyData;
        JSONObject retObj = buildRetObj();
        Map<String, String> payContext = new HashMap();

        String respString = ZypayConfig.RETURN_VALUE_FAIL;
        try {
            PayOrder payOrder = verifyPayParams(request, payContext);
            if( payOrder == null ) { //验证参数失败
                retObj.put(PayConstant.RESPONSE_RESULT, ZypayConfig.RETURN_VALUE_FAIL);
                return retObj;
            }
            //订单已经支付完成
            if(payOrder.getStatus() == PayConstant.PAY_STATUS_SUCCESS || payOrder.getStatus() == PayConstant.PAY_STATUS_COMPLETE){
                retObj.put(PayConstant.RESPONSE_RESULT, ZypayConfig.RETURN_VALUE_OK);
                return retObj;
            }
            //上游通知 状态
            String channelOrderNo = payContext.get("queryId"); //上游订单号

            int updatePayOrderRows = commonService.payOrderService.updateStatus4Success(payOrder.getPayOrderId(), channelOrderNo);
            if (updatePayOrderRows != 1) {
                _log.error("{}更新支付状态失败,将payOrderId={},更新payStatus={}失败", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
                retObj.put(PayConstant.RESPONSE_RESULT, "处理订单失败");
                return retObj;
            }
            _log.error("{}更新支付状态成功,将payOrderId={},更新payStatus={}成功", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
            payOrder.setStatus(PayConstant.PAY_STATUS_SUCCESS);

            // 业务系统后端通知
            baseNotify4MchPay.doNotify(payOrder, true);
            _log.info("====== 完成处理ZY支付回调通知 ======");
            respString = ZypayConfig.RETURN_VALUE_OK;
        } catch (Exception e) {
            _log.error(e, logPrefix + "处理异常");
        }
        retObj.put(PayConstant.RESPONSE_RESULT, respString);
        return retObj;
    }

    /**
     * 验证ZY通知参数
     * @return
     */
    public PayOrder verifyPayParams(HttpServletRequest request, Map<String, String> payContext) {

        // 校验结果是否成功
        String memberid = request.getParameter("memberid");             // 商户编号
        String amount = request.getParameter("amount");                 // 订单金额
        String orderid = request.getParameter("orderid");		          // 订单号
        String datetime = request.getParameter("datetime");		      // 交易时间
        String sign = request.getParameter("sign"); 		              // 签名
        String transaction_id = request.getParameter("transaction_id"); // 交易流水号
        String returncode = request.getParameter("returncode");         // “00” 为成功
        String attach = request.getParameter("attach");                 // 商户附加数据返回

        _log.info("[{}]memberid={}, amount={}, orderid={}, sign={}, datetime={}, transaction_id={}, returncode={}, attach={}",
                logPrefix, memberid, amount, orderid, sign, datetime, transaction_id, returncode, attach);

        //状态核对
        if(!"00".equals(returncode)) {
            _log.info("[{}]orderid={} 返回失败", getChannelName(), orderid);
            return null;
        }

        // 查询payOrder记录
        String payOrderId = orderid;
        PayOrder payOrder = commonService.payOrderService.findByPayOrderId(payOrderId);
        if (payOrder == null) {
            _log.error("Can't found payOrder form db. payOrderId={}, ", payOrderId);
            return null;
        }

        ZypayConfig zypayConfig = new ZypayConfig(getPayParam(payOrder));
        Map<String, Object> paramMap = new TreeMap();
        paramMap.put("memberid", memberid);
        paramMap.put("orderid", orderid);
        paramMap.put("amount", amount);
        paramMap.put("transaction_id", transaction_id);
        paramMap.put("datetime", datetime);
        paramMap.put("returncode", returncode);
        //生成签名
        String signValue = ZypayUtil.getSign(paramMap, zypayConfig.getKey());
        // 验证签名
        if(!sign.equals(signValue)) {
            _log.error("验证签名失败. payOrderId={}, ", payOrderId);
            return null;
        }
        //上游订单号
        payContext.put("queryId", transaction_id);
        return payOrder;
    }

    public static void main(String[] args){
        Map<String, Object> paramMap = new TreeMap();
        paramMap.put("memberid", "1");
        paramMap.put("orderid", "P01201908211703038710018");
        paramMap.put("amount", "300.00");
        paramMap.put("transaction_id", "123456");
        paramMap.put("datetime", "2019-01-01 10:10:10");
        paramMap.put("returncode", "00");
        //生成签名
        String signValue = ZypayUtil.getSign(paramMap, "123");

        String format = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println(format);
        System.out.println(signValue);
    }

}
